﻿
using AspectCore.Configuration;
using AspectCore.DynamicProxy;
using AspectCore.Extensions.DependencyInjection;
using Autofac;
using Autofac.Core;
using Autofac.Extras.DynamicProxy;
using Castle.Core;
using Castle.DynamicProxy;
using JGSY.SerialCommunication.UpperComputer;
using JGSY.SerialCommunication.UpperComputer.Core.AOP;
using JGSY.SerialCommunication.UpperComputer.Core.AOP.AspectCore; 
using JGSY.SerialCommunication.UpperComputer.Core.AOP.Decorator;
using JGSY.SerialCommunication.UpperComputer.Core.AOP.ThirdPartyLibrary;
using JGSY.SerialCommunication.UpperComputer.Core.AOP.ThirdPartyLibrary.Proxy;
using JGSY.SerialCommunication.UpperComputer.Modbus;
using Microsoft.Extensions.DependencyInjection;
using PostSharp.Aspects;
using PostSharp.Extensibility;
using PostSharp.Serialization;
using RJCP.IO.Ports;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Reflection;
using System.Security.Authentication.ExtendedProtection;
using System.Security.Permissions;

namespace JGSY.SerialCommunication
{
    internal class Program
    {

        static void Main(string[] args)
        {
            //Modbus_Case();

            AOP七种实现();
            {


                //var builder = new ContainerBuilder(); // 创建容器构建器
                //builder.RegisterType<LogAutofacInterceptor>();  // 注册拦截器
                //builder.RegisterType<BankServes>().As<IBankServes>()
                //    .EnableInterfaceInterceptors()
                //    .InterceptedBy(typeof(LogAutofacInterceptor)); // 注册服务并启用拦截
                //var container = builder.Build(); // 构建容器


                //using (var scope = container.BeginLifetimeScope())// 解析服务
                //{
                //    var orderService = scope.Resolve<IBankServes>();
                //    orderService.TarnsferMoney(100); // 调用服务方法
                //}
            }
            {
                //var builder = new ContainerBuilder();
                //// 注册拦截器
                //builder.RegisterType<LogAutofacInterceptor>().As<Castle.DynamicProxy.IInterceptor>();
                //// 修正：指定具体程序集进行扫描
                //var targetAssembly = Assembly.GetAssembly(typeof(BankServes));
                //// 批量注册服务并应用拦截器
                ////builder.RegisterAssemblyTypes(typeof(Program).Assembly)
                //builder.RegisterAssemblyTypes(targetAssembly)
                //           .Where(t => t.Name.EndsWith("Serves") &&    // 确认命名正确
                //                  !t.IsAbstract &&                // 排除抽象类
                //                  t.GetInterfaces().Any())        // 确保实现了接口
                //       .AsImplementedInterfaces()// 必须注册为接口
                //       .EnableInterfaceInterceptors() //Autofac.Extras.DynamicProxy
                //       .InterceptedBy(typeof(LogAutofacInterceptor));

                //// 如果你有多个程序集，可以这样注册
                //// builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
                ////        .Where(t => t.Namespace != null && t.Namespace.Contains("Services"))
                ////        .AsImplementedInterfaces()
                ////        .EnableInterfaceInterceptors()
                ////        .InterceptedBy(typeof(LogAutofacInterceptor));



                //builder.RegisterType<BankServes>().As<IBankServes>();
                //var container = builder.Build();

                //using (var scope = container.BeginLifetimeScope())
                //{
                //    var orderService = scope.Resolve<IBankServes>();
                //    orderService.TarnsferMoney(100);
                //}
            }
             


        }
        // 获取所有包含服务的程序集
        private static Assembly[] GetServiceAssemblies()
        {
            return AppDomain.CurrentDomain.GetAssemblies()
                .Where(a => !a.IsDynamic &&               // 排除动态程序集
                           a.FullName.Contains("Service")) // 筛选名称包含"Service"的程序集
                .ToArray();
        }
        private static void AOP七种实现()
        {
            // AOP 
            //DispatchProxy：.NET 内置类，使用更简单，但只能代理接口，且需要继承特定基类。
            //Castle DynamicProxy：第三方库，功能更强大，支持代理类（不仅限于接口），使用更灵活。

            //NET内置运行时动态代理（手动实现）  反射 继承DispatchProxy
            //1、静态Create 2、重写Invoke 添加前后逻辑
            IBankServes service = DynamicProxy<IBankServes>.Create(new BankServes());
            service.TarnsferMoney(1000); // 正常调用
            service.TarnsferMoney(-100); // 触发异常

            //LogCastleDynamicProxyInterceptor **********************************************
            // 创建代理生成器
            var proxyGenerator = new Castle.DynamicProxy.ProxyGenerator();
            // 创建拦截器实例
            var interceptor = new LogCastleDynamicProxyInterceptor();
            // 创建目标对象
            var targateService = new BankServes();
            // 生成代理对象
            var proxyService = proxyGenerator.CreateInterfaceProxyWithTargetInterface<IBankServes>(targateService, interceptor);


            // 调用代理方法
            Console.WriteLine("=== 正常调用示例 ===");
            proxyService.TarnsferMoney(1000);

            Console.WriteLine("=== 异常调用示例 ===");
            proxyService.TarnsferMoney(0);

            // ProxyFactoryCastleDynamicProxy **********************************************
            //对上一个的封装 创建代理生成器 创建拦截器实例 创建目标对象
            //自定义特性 + 动态代理
            //1 通过自定义LogAspectAttribute特性实现方法拦截逻辑
            //2 使用 Castle DynamicProxy 实现动态代理
            //3 支持对方法参数、返回值和异常的统一处理
            //4 实现了基于特性的拦截器自动注册机制
            var userService1 = new BankServes();
            var proxyService1 = ProxyFactoryCastleDynamicProxy.CreateProxy<IBankServes>(userService1);
            // 调用代理方法
            Console.WriteLine("=== 正常调用示例 ===");
            proxyService.TarnsferMoney(1000);

            Console.WriteLine("=== 异常调用示例 ===");
            proxyService.TarnsferMoney(0);
            //**********************************************
            /***
     * 实现 【标记（Flag）接口 + Castle 】复杂拦截逻辑 
     * 1、定义拦截器标记接口
     * 2、定义自定义拦截器属性
     * 3、实现 IInterceptor 接口的日志拦截器 
     * 4、用于标记代理对象的混入类
     * 5、AOP代理工厂
     * 6、选择性拦截器
     * 7、实现标记接口的服务类
     *  
     *  
     * */
            var proxyService2 = ProxyFactoryFlag.CreateProxy<BankServes>();

            Console.WriteLine("=== 调用带 Log 特性的方法 ===");
            Console.WriteLine("=== 正常调用示例 ===");
            proxyService2.TarnsferMoney(1000);

            Console.WriteLine("\n=== 调用不带 Log 特性的方法 ===");
            Console.WriteLine("=== 异常调用示例 ===");
            proxyService2.TarnsferMoney2(10);

            //**********************************************
            // Decorate 模式
            JGSY.SerialCommunication.UpperComputer.Core.AOP.Decorator.IService serviceDecorator = new ConcreteService();
            serviceDecorator = new LoggingDecorator(serviceDecorator);
            serviceDecorator = new CachingDecorator(serviceDecorator);

            serviceDecorator.Execute();


            // AspectCore**********************************************

            // Microsoft.Extensions.DependencyInjection
            var serviceCollection = new ServiceCollection();
            // 配置 AspectCore 动态代理
            serviceCollection.ConfigureDynamicProxy(config =>
            {



                //config.ProxyInterceptors.Generator = new CastleDynamicProxyGenerator();
                //全局注册方式 config.Interceptors.AddTyped<LogAspectDNC>(); 会将 LoggingAspect 应用到 所有符合条件的服务方法：
                //无需额外条件，AspectCore 会自动扫描并应用到所有：
                //标记了[LoggingAspect] 特性的方法
                //实现了 IInterceptor 接口的拦截器类
                //适用于统一管理所有拦截器的场景
                //config.Interceptors.AddTyped<LogAspectDNC>(m => true);  m => true全局注册方式
                // 启用方法拦截（使用更简单的方式）
                config.Interceptors.AddTyped<LogAspectDNC>(m => true);
                //// 只拦截 UserService 类的方法
                //m => m.DeclaringType == typeof(UserService)

                //// 只拦截名称以 "Get" 开头的方法
                //m => m.Name.StartsWith("Get")

                //// 只拦截标记了特定特性的方法
                //m => m.GetCustomAttributes(typeof(CacheableAttribute), true).Any()

            });
            //// 注册服务和拦截器
            //services.AddDynamicProxy(config =>
            //{
            //    config.Interceptors.AddTyped<LoggingAttribute>(Predicates.ForService("*Service"));
            //});
            // 注册服务
            serviceCollection.AddTransient<IBankServes, BankServes>();
            // 使用 AspectCore 的 ServiceProvider 工厂创建服务容器
            //  使用 AspectCore 扩展方法 
            var provider = serviceCollection.BuildServiceContextProvider();// 支持AOP
            //var provider = serviceCollection.BuildServiceProvider(); 不支持AOP .NET 原生 DI
            //var provider = serviceCollection.BuildDynamicProxyProvider();旧版本支持AOP AspectCore (旧)

            var service4 = provider.GetRequiredService<IBankServes>();
            service4.TarnsferMoney(1000);



        }


        /// <summary>
        /// Modbus测试
        /// </summary>
        private static void Modbus_Case()
        {

            //try
            //{
            //    // 创建 Modbus 客户端（TCP 协议）
            //    using var client = new ModbusClient(ipAddress:"127.0.0.1",port:502);
            //    await client.ConnectAsync();

            //    // 读取浮点数（温度值）
            //    float temperature = await client.ReadValueAsync<float>(slaveId:1, startAddress:0);
            //    Console.WriteLine($"温度: {temperature}°C");

            //    // 写入浮点数
            //    await client.WriteValueAsync(1, 100, 25.5f);
            //    Console.WriteLine("已写入温度: 25.5°C");

            //    // 读取整数（计数器值）
            //    int counter = await client.ReadValueAsync<int>(1, 200);
            //    Console.WriteLine($"计数器: {counter}");

            //    // 写入长整数
            //    await client.WriteValueAsync(1, 300, 1234567890L);
            //    Console.WriteLine("已写入长整数");

            //    // 读取双精度浮点数
            //    double pressure = await client.ReadValueAsync<double>(1, 400);
            //    Console.WriteLine($"压力: {pressure} MPa");

            //    // 使用不同的字节序读取数据
            //    float specialValue = await client.ReadValueAsync<float>(1, 500, ByteOrder.MidLittleEndian);
            //    Console.WriteLine($"特殊值: {specialValue}");
            //}
            //catch (Exception ex)
            //{
            //    Console.WriteLine($"错误: {ex.Message}");
            //}

            try
            {
                #region ModbusRtu

                // 初始化 ModbusRtu 实例
                ModbusRtu modbusRtu = new ModbusRtu("COM1", 9600, 8, Parity.None, StopBits.One, 50);

                // 构建 PDU 
                // 发送请求并接收响应  

                #region ModbusRtu 1234读


                //var response1 = modbusRtu.ReadCoils(slaveNum: 1, funcCode: 0x01, startAddr: 0, count: 5);


                //var response2 = modbusRtu.ReadCoils(slaveNum: 1, funcCode: 0x02, startAddr: 0, count: 5);


                //var response3 = modbusRtu.ReadRegisters<ushort>(slaveNum: 1, funcCode: 0x03, startAddr: 0, dataCount: 5);

                //var response4 = modbusRtu.ReadRegisters<ushort>(slaveNum: 1, funcCode: 0x04, startAddr: 0, dataCount: 5);
                Console.WriteLine();
                #endregion


                #region ModbusRtu 线圈 5/15写单个多个 

                //List<bool> boolValues1 = new List<bool>() { true };

                //var responseWrite1 = modbusRtu.WriteCoils(slaveNum: 1, startAddr: 0, boolValues1);


                //List<bool> boolValues = new List<bool>() { true, true, true, false, true, true, };

                //var responseWrite2 = modbusRtu.WriteCoils(slaveNum: 1, startAddr: 0, boolValues);
                Console.WriteLine();

                #endregion

                #region ModbusRtu 寄存器6/16写单个多个

                //List<ushort> ushorts1 = new List<ushort>() { 55 };
                //var responseWrite2 = modbusRtu.WriteRegisters<ushort>(slaveNum: 1, startAddr: 4, ushorts1);

                //List<ushort> ushorts = new List<ushort>() { 99, 88, 77, 66, 55 };
                //var responseWrite4 = modbusRtu.WriteRegisters<ushort>(slaveNum: 1, startAddr: 0, ushorts);
                Console.WriteLine();
                #endregion

                #endregion


                #region ModbusASCII

                // 初始化 ModbusASCII 实例
                ModbusAscii modbusAscii = new ModbusAscii("COM1", 9600, 8, Parity.None, StopBits.One, 50);

                // 构建 PDU 
                // 发送请求并接收响应  

                #region ModbusASCII 1234读


                //var response12 = modbusAscii.ReadCoils(slaveNum: 1, funcCode: 0x01, startAddr: 0, count: 5);

                //var response2 = modbusAscii.ReadCoils(slaveNum: 1, funcCode: 0x02, startAddr: 0, count: 5);


                //var response3 = modbusAscii.ReadRegisters<ushort>(slaveNum: 1, funcCode: 0x03, startAddr: 0, dataCount: 5);

                //var response4 = modbusAscii.ReadRegisters<ushort>(slaveNum: 1, funcCode: 0x04, startAddr: 0, dataCount: 5);
                Console.WriteLine();
                #endregion


                #region ModbusASCII 线圈 5/15写单个多个 

                //List<bool> boolValues1 = new List<bool>() { true };

                //var responseWrite1 = modbusAscii.WriteCoils(slaveNum: 1, startAddr: 0, boolValues1);


                //List<bool> boolValues = new List<bool>() { false, true, true, false, true, true, };

                //var responseWrite2 = modbusAscii.WriteCoils(slaveNum: 1, startAddr: 0, boolValues);

                Console.WriteLine();
                #endregion

                #region ModbusASCII 寄存器6/16写单个多个

                //List<ushort> ushorts1 = new List<ushort>() { 111 };
                //var responseWrite2 = modbusAscii.WriteRegisters<ushort>(slaveNum: 1, startAddr: 0, ushorts1);

                //List<ushort> ushorts = new List<ushort>() { 222, 333, 444, 555, 666 };
                //var responseWrite4 = modbusAscii.WriteRegisters<ushort>(slaveNum: 1, startAddr: 0, ushorts);
                Console.WriteLine();
                #endregion

                #endregion


                #region ModbusTCP

                // 初始化 ModbusASCII 实例
                ModbusTcp modbusTcp = new ModbusTcp("127.0.0.1", 502);

                // 构建 PDU 
                // 发送请求并接收响应  

                #region ModbusTCP 1234读


                //var response13 = modbusTcp.ReadCoils(slaveNum: 1, funcCode: 0x01, startAddr: 0, count: 5);

                //var response2 = modbusTcp.ReadCoils(slaveNum: 1, funcCode: 0x02, startAddr: 0, count: 5);


                //var response3 = modbusTcp.ReadRegisters<ushort>(slaveNum: 1, funcCode: 0x03, startAddr: 0, dataCount: 5);

                //var response4 = modbusTcp.ReadRegisters<ushort>(slaveNum: 1, funcCode: 0x04, startAddr: 0, dataCount: 5);
                Console.WriteLine();

                #endregion


                #region modbusTcp 线圈 5/15写单个多个 

                //List<bool> boolValues1 = new List<bool>() { true };

                //var responseWrite1 = modbusTcp.WriteCoils(slaveNum: 1, startAddr: 0, boolValues1);


                //List<bool> boolValues = new List<bool>() { false, true, true, false, true, true, };

                //var responseWrite2 = modbusTcp.WriteCoils(slaveNum: 1, startAddr: 0, boolValues);

                Console.WriteLine();

                #endregion

                #region modbusTcp 寄存器6/16写单个多个

                //List<ushort> ushorts1 = new List<ushort>() { 111 };
                //var responseWrite5 = modbusTcp.WriteRegisters<ushort>(slaveNum: 1, startAddr: 0, ushorts1);

                //List<ushort> ushorts = new List<ushort>() { 222, 333, 444, 555, 666 };
                //var responseWrite4 = modbusTcp.WriteRegisters<ushort>(slaveNum: 1, startAddr: 0, ushorts);
                Console.WriteLine();
                #endregion



                #endregion


                #region ModbusUdp

                // 初始化 ModbusASCII 实例
                ModbusUDP modbusUdp = new ModbusUDP("127.0.0.1", 502);
                //ModbusUDP modbusUdp = new ModbusUDP("127.0.0.1", 502, isIgnore: true);//不兼容Modbus

                // 构建 PDU 
                // 发送请求并接收响应  

                #region ModbusUdp 1234读


                //var response14 = modbusUdp.ReadCoils(slaveNum: 1, funcCode: 0x01, startAddr: 0, count: 5);

                //var response2 = modbusUdp.ReadCoils(slaveNum: 1, funcCode: 0x02, startAddr: 0, count: 5);


                //var response3 = modbusUdp.ReadRegisters<ushort>(slaveNum: 1, funcCode: 0x03, startAddr: 0, dataCount: 5);

                //var response4 = modbusUdp.ReadRegisters<ushort>(slaveNum: 1, funcCode: 0x04, startAddr: 0, dataCount: 5);
                Console.WriteLine();
                #endregion


                #region ModbusUdp 线圈 5/15写单个多个 

                //List<bool> boolValues1 = new List<bool>() { true };

                //var responseWrite1 = modbusUdp.WriteCoils(slaveNum: 1, startAddr: 0, boolValues1);


                //List<bool> boolValues = new List<bool>() { false, true, true, false, true, true, };

                //var responseWrite2 = modbusUdp.WriteCoils(slaveNum: 1, startAddr: 0, boolValues);

                Console.WriteLine();

                #endregion

                #region ModbusUdp 寄存器6/16写单个多个

                //List<ushort> ushorts1 = new List<ushort>() { 111 };
                //var responseWrite5 = modbusUdp.WriteRegisters<ushort>(slaveNum: 1, startAddr: 0, ushorts1);

                //List<ushort> ushorts = new List<ushort>() { 222, 333, 444, 555, 666 };
                //var responseWrite4 = modbusUdp.WriteRegisters<ushort>(slaveNum: 1, startAddr: 0, ushorts);
                Console.WriteLine();
                #endregion



                #endregion


                #region Modbus Tcp 报文
                int flag = 9;
                if (flag == 19)
                {
                    List<byte> dataBytes = new List<byte>();
                    dataBytes.Add(0x01);// 从站地址
                    dataBytes.Add(0x03);// 功能码     20->14    0x31  0x34      0x32  0x30
                    ushort addr = 5;// 起始地址
                    dataBytes.Add((byte)(addr / 256));
                    dataBytes.Add((byte)(addr % 256));
                    ushort len = 4;// 读取寄存器数量 
                    dataBytes.Add((byte)(len / 256));
                    dataBytes.Add((byte)(len % 256));


                    // [] [] [0] [1] [2] [3] [4] [5] [6] 
                    // [0] [1]  0x00 0x01

                    List<byte> headerBytes = new List<byte>();
                    ushort tid = 0;
                    // 如果用Insert   先插入  长度 - pid - tid
                    //dataBytes.Insert(0, (byte)(tid % 256));
                    //dataBytes.Insert(0, (byte)(tid / 256));
                    // tid

                    // Socket
                    Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    socket.Connect("127.0.0.1", 502);

                    while (tid < 2)
                    {
                        tid++;
                        headerBytes.Add((byte)(tid / 256));
                        headerBytes.Add((byte)(tid % 256));
                        // pid
                        headerBytes.Add(0x00);
                        headerBytes.Add(0x00);
                        // len
                        headerBytes.Add((byte)(dataBytes.Count / 256));
                        headerBytes.Add((byte)(dataBytes.Count % 256));

                        headerBytes.AddRange(dataBytes);

                        socket.Send(headerBytes.ToArray());
                    }

                    // 接收解析
                    byte[] bytes = new byte[len * 2 + 9];
                    socket.Receive(bytes, 0, bytes.Length, SocketFlags.None); // 卡线程


                    ParseModbusResponse(bytes);

                    // 协议  字节长度  
                    // 先获取 6个长度的字节    byte[6]    取出最后两个字节计算PDU部分
                    // 串行不建议分组处理   一次获取所有有效字节  需要进行相关的校验查
                }
                #endregion
            }
            catch (Exception ex)
            {
                Console.WriteLine("通信失败: " + ex.Message);
            }
        }

        static void ParseModbusResponse(byte[] response)
        {
            try
            {
                // 解析MBAP头
                ushort transactionId = (ushort)(response[0] * 256 + response[1]);
                ushort protocolId = (ushort)(response[2] * 256 + response[3]);
                ushort length = (ushort)(response[4] * 256 + response[5]);
                byte unitId = response[6];
                byte functionCode = response[7];

                Console.WriteLine($"--- 响应解析 ---");
                Console.WriteLine($"事务ID: {transactionId}");
                Console.WriteLine($"协议ID: {protocolId}");
                Console.WriteLine($"长度: {length}");
                Console.WriteLine($"单元ID: {unitId}");
                Console.WriteLine($"功能码: {functionCode}");

                // 检查异常
                if ((functionCode & 0x80) != 0)
                {
                    byte errorCode = response[8];
                    Console.WriteLine($"异常响应: 功能码 {functionCode & 0x7F}, 错误码 {errorCode}");
                    return;
                }

                // 解析数据
                switch (functionCode)
                {
                    case 0x03: // 读保持寄存器
                        byte byteCount = response[8];
                        Console.WriteLine($"字节数: {byteCount}");
                        Console.WriteLine($"寄存器值:");

                        for (int i = 0; i < byteCount; i += 2)
                        {
                            ushort regValue = (ushort)(response[9 + i] * 256 + response[10 + i]);
                            Console.WriteLine($"  寄存器 {(i / 2) + 5}: {regValue}");
                        }
                        break;

                    default:
                        Console.WriteLine($"未处理的功能码: {functionCode}");
                        break;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"解析错误: {ex.Message}");
            }
        }

    }
}